<template>
  <scroll-view scroll-y :style="{ height: props.height + 'rpx' }" @scrolltolower="onScrollToBottom">
    <refresh :display="showLoading ? 'show' : 'hide'" @refresh="onrefresh" @pullingdown="onpullingdown">
      <slot name="pull" :status="{ refreshStatus }">
        <view
          class="flex flex-row flex-row-center-center"
          :style="{
            height: _barHeight / 2 + 'px',
            opacity: refreshStatus == 2 || refreshStatus == 3 ? 1 : 0,
          }"
        >
          <tm-icon :font-size="24" color="primary" name="tmicon-shuaxin" spin></tm-icon>
          <tm-text color="grey" _class="pl-16" :label="loadingTexts[refreshStatus]"></tm-text>
        </view>
        <view
          v-if="refreshStatus != -1 && refreshStatus != 2"
          class="flex flex-row flex-row-center-center srrryration"
          :style="{
            opacity: `${refreshStatus == 0 ? _barHeight / nowEvt.viewHeight : 1}`,
            height: _barHeight / 2 + 'px',
          }"
        >
          <view :class="refreshStatus == 0 ? 'srrryration srrryrationOn' : 'srrryration srrryrationOf'">
            <tm-icon :font-size="24" color="primary" name="tmicon-long-arrow-down"></tm-icon>
          </view>
          <tm-text color="grey" _class="pl-16" :label="loadingTexts[refreshStatus]"></tm-text>
        </view>
      </slot>
    </refresh>
    <slot></slot>
  </scroll-view>
</template>

<script lang="ts" setup>
import tmIcon from '../tm-icon/tm-icon.vue'
import tmText from '../tm-text/tm-text.vue'
import { getCurrentInstance, nextTick, onMounted, ref, Ref, watch } from 'vue'
import { propsdetail } from './propsdetail'
const proxy = getCurrentInstance()?.proxy ?? null
const emits = defineEmits(['bottom', 'change', 'refresh', 'timeout', 'update:modelValue', 'update:bottomValue'])
const props = defineProps({
  ...propsdetail,
})
interface pullevent {
  dy: number
  pullingDistance: number
  viewHeight: number
  type: string
}
const showLoading = ref(false)
const refreshing = ref(false)
const isBootRefresh = ref(false)
const refreshStatus = ref(-1)
/** 开始刷新 - 刷新成功/失败 最大间隔时间setTimeout句柄 */
let maxRefreshAnimateTimeFlag: number | null = 0
const _barHeight = ref(uni.$tm.u.topx(props.loadBarHeight))
const nowEvt: Ref<pullevent> = ref({
  dy: 0,
  pullingDistance: 0,
  viewHeight: 0,
  type: '',
})

onMounted(() => {
  if (maxRefreshAnimateTimeFlag != null) {
    clearTimeout(maxRefreshAnimateTimeFlag)
  }
})
watch(
  () => props.modelValue,
  () => {
    if (!props.modelValue) {
      if (maxRefreshAnimateTimeFlag != null) {
        clearTimeout(maxRefreshAnimateTimeFlag)
      }
      close()
    }
  }
)
watch(
  () => props.bottomValue,
  () => {
    isBootRefresh.value = props.bottomValue
  }
)
function onScrollToBottom() {
  if (isBootRefresh.value) return
  emits('update:bottomValue', true)
  isBootRefresh.value = true
  emits('bottom')
}
function onrefresh() {
  if (nowEvt.value.pullingDistance >= _barHeight.value) {
    refreshStatus.value = 2
    showLoading.value = true
    emits('refresh')
    emits('change', true)
    emits('update:modelValue', true)
    maxRefreshAnimateTimeFlag = setTimeout(() => {
      maxRefreshAnimateTimeFlag = null
      if (refreshStatus.value === 2) {
        // 超时回调
        emits('timeout')
        close() // 超时仍未被回调，则直接结束下拉
      }
    }, props.refreshTimeout as any) as any as number

    return
  }
  if (refreshStatus.value == -1 || refreshStatus.value == 0) {
    showLoading.value = true
    nextTick(() => {
      showLoading.value = false
      emits('change', false)
    })
  }
}
/**
	 * dy: 前后两次回调滑动距离的差值
	pullingDistance: 下拉的距离
	viewHeight: refresh 组件高度
	type: “pullingdown” 常数字符串
	 */
function onpullingdown(evt: { dy: number; pullingDistance: number; viewHeight: number; type: string }) {
  nowEvt.value = evt

  if (evt.pullingDistance <= 1) {
    refreshStatus.value = -1
  } else if (evt.pullingDistance > 1 && evt.pullingDistance < _barHeight.value) {
    refreshStatus.value = 0
  } else if (evt.pullingDistance >= _barHeight.value) {
    refreshStatus.value = 1
  }
}

function close() {
  showLoading.value = false
  refreshStatus.value = 3
  emits('change', false)
  emits('update:modelValue', false)
}
</script>

<style>
.srrryration {
  transition-property: transform, height, opacity;
  transition-timing-function: ease;
  transition-duration: 0.25s;
}

.srrryrationOn {
  transform: rotate(0deg);
}

.srrryrationOf {
  transform: rotate(180deg);
}
</style>
